﻿using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Flatland.GeneticProgramming;
using Flatland.GeneticProgramming.CoreTypes;

namespace Flatland.AgentBehavior
{
    /// <summary>
    /// Subsume a behavior to a layer
    /// </summary>
    [AttributeUsage(AttributeTargets.Field)]
    internal class Subsume : Attribute
    {
        /// <summary>
        /// Report for the GenoType.
        /// </summary>
        public Report Report { get; set; }

        /// <summary>
        /// Attribute constructor. 
        /// </summary>
        /// <param name="genotype">The GenoType</param>
        public Subsume(Type genotype) {
            GP gp = new GeneticProgramming.GP((GenoType)Activator.CreateInstance(genotype), populationSize: 1);
            gp.EvaluateFitness = false; //Would trigger fitness call to agent we are building
            gp.Init();
            if (gp.Population.Count == 0)
                throw new Exception(
                    "Cannot create agent gene. GP population size must be above zero after initialization");
            Report = gp.Population[0];
        }

        /// <summary>
        /// Attribute constructor. 
        /// </summary>
        /// <param name="genefile">File name of the phenotype. Normally a .PhenoType file.</param>
        public Subsume(string phenotypeFile)
        {
            if (!phenotypeFile.Contains(Program.MY_GENES_FOLDER))
                phenotypeFile = Program.MY_GENES_FOLDER + "\\" + phenotypeFile;
            if (!phenotypeFile.Contains(Program.GENE_FILE_EXTENSION))
                phenotypeFile += Program.GENE_FILE_EXTENSION;
            IFormatter formatter2 = new BinaryFormatter();
            using (Stream stream = new FileStream(phenotypeFile, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                try{
                    Report = (Report) formatter2.Deserialize(stream);
                }
                catch (Exception e)
                {
                    throw new FileLoadException(
                        "Provided genefile was invalid. Make sure you use a .Gene file. Exception: " + e);
                }
                stream.Close();
            }
        }
    }
}
